#ifndef __UPSTREAM_H__
#define __UPSTREAM_H__

#define UPSTREAM_PROTOCAL_RAW 0
#define UPSTREAM_PROTOCAL_MC 1
#define UPSTREAM_PROTOCAL_REDIS 2

typedef int (*async_event_done_pt)(struct Task *pTask);
typedef int (*process_upstream_response_pt)(struct Upstream *up);

/* 1 downstream : N upstream */
typedef struct Task {
    Conn *conn;             /* the main connection(downstream) */
    ds_array_s *upstreams;  /* the upstreams */
    async_event_done_pt handler;    /* When all the upstream events done, the handler will be invoked */
}Task;

typedef struct Upstream {
    void *data;
    
    Chain *request_buf;
    Chain *response_buf;
    
    unsigned int err:1;
    unsigned int eof:1;         /* eof means that the backend server close the socket
                                                        while complete means that user checks if the received data 
                                                        match their logic */
    unsigned int complete:1;

    size_t rcvlen;
    
    char host[16];
    int port;

    Conn *peer;
    Task *parent;

    process_upstream_response_pt handler;
}Upstream;


Upstream * CreateUpsteam(Task *task, int protocol, char *ip, int port);
int AddUpstreamRequestBuf(Upstream *upstream, char *buf, size_t len);
Task * CreateTaskTable(Conn *conn, async_event_done_pt handler);
int AddTask(Upstream *upstream, Task *task);
int RunTaskEngine(Task *task);

#endif

